package com.xyht.sca_s.student_manage_system.modules.asset.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import com.xyht.sca_s.student_manage_system.common.commonReturn.CommonCodeEnum;
import com.xyht.sca_s.student_manage_system.common.commonReturn.CommonResult;
import com.xyht.sca_s.student_manage_system.common.commonReturn.ExceptionCast;
import com.xyht.sca_s.student_manage_system.common.commonReturn.ResponseResult;
import com.xyht.sca_s.student_manage_system.common.util.CacheUtil;
import com.xyht.sca_s.student_manage_system.common.util.TimeUtil;
import com.xyht.sca_s.student_manage_system.modules.asset.entity.*;
import com.xyht.sca_s.student_manage_system.modules.asset.entity.req.fixedInStorageApply.SmsAssetFixedInStorageApplyAllowReq;
import com.xyht.sca_s.student_manage_system.modules.asset.entity.req.fixedInStorageApply.SmsAssetFixedInStorageApplyGoodsReq;
import com.xyht.sca_s.student_manage_system.modules.asset.entity.req.fixedInStorageApply.SmsAssetFixedInStorageApplyProcessDetailReq;
import com.xyht.sca_s.student_manage_system.modules.asset.entity.req.fixedInStorageApply.SmsAssetFixedInStorageApplyReq;
import com.xyht.sca_s.student_manage_system.modules.asset.entity.resp.fixedInStorageApply.SmsAssetFixedInStorageApplyGoodsResp;
import com.xyht.sca_s.student_manage_system.modules.asset.entity.resp.fixedInStorageApply.SmsAssetFixedInStorageApplyMPJResp;
import com.xyht.sca_s.student_manage_system.modules.asset.entity.resp.fixedInStorageApply.SmsAssetFixedInStorageApplyProcessDetailResp;
import com.xyht.sca_s.student_manage_system.modules.asset.entity.resp.fixedInStorageApply.SmsAssetFixedInStorageApplyResp;
import com.xyht.sca_s.student_manage_system.modules.asset.mapper.*;
import com.xyht.sca_s.student_manage_system.modules.asset.service.SmsAssetFixedInStorageApplyService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xyht.sca_s.student_manage_system.modules.asset.util.AssetUtil;
import com.xyht.sca_s.student_manage_system.modules.newTips.myEnum.AppTypeEnum;
import com.xyht.sca_s.student_manage_system.modules.newTips.myEnum.RangeTypeEnum;
import com.xyht.sca_s.student_manage_system.modules.newTips.myEnum.TipsTypeEnum;
import com.xyht.sca_s.student_manage_system.modules.newTips.util.NewTipsUtil;
import com.xyht.sca_s.student_manage_system.modules.user.entity.SmsRole;
import com.xyht.sca_s.student_manage_system.modules.user.entity.SmsUser;
import com.xyht.sca_s.student_manage_system.modules.user.entity.resp.SmsSearchUserResp;
import com.xyht.sca_s.student_manage_system.modules.user.mapper.SmsRoleMapper;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

import static com.xyht.sca_s.student_manage_system.common.constant.CommonConstant.APPLY_MAX_SIZE;
import static com.xyht.sca_s.student_manage_system.common.util.ParamCheckUtil.isNullOrEmpty;
import static com.xyht.sca_s.student_manage_system.modules.asset.constant.AssetAllowStatusConstant.*;
import static com.xyht.sca_s.student_manage_system.modules.asset.constant.AssetAllowTypeConstant.*;
import static com.xyht.sca_s.student_manage_system.modules.asset.constant.AssetBooleanConstant.ASSET_BOOLEAN_FALSE;
import static com.xyht.sca_s.student_manage_system.modules.asset.constant.AssetBooleanConstant.ASSET_BOOLEAN_TRUE;
import static com.xyht.sca_s.student_manage_system.modules.asset.constant.AssetObjectTypeConstant.ASSET_OBJECT_TYPE_PERSON;
import static com.xyht.sca_s.student_manage_system.modules.asset.constant.AssetProcessTypeConstant.ASSET_PROCESS_TYPE_FIXED_IN_STORAGE;
import static com.xyht.sca_s.student_manage_system.modules.asset.constant.AssetStatusConstant.ASSET_STATUS_IN_STORAGE;
import static com.xyht.sca_s.student_manage_system.modules.asset.constant.CommonConstant.EXAMINE_STATUS_PASS;
import static com.xyht.sca_s.student_manage_system.modules.asset.constant.CommonConstant.EXAMINE_STATUS_WAIT_ALLOW;
import static com.xyht.sca_s.student_manage_system.modules.asset.constant.InStorageMethodConstant.IN_STORAGE_METHOD_FIXED_APPLY;
import static com.xyht.sca_s.student_manage_system.modules.asset.constant.ProcessObjectTypeConstant.PROCESS_OBJECT_TYPE_PERSON;

/**
 * <p>
 * 固定资产入库申请 服务实现类
 * </p>
 *
 * @author XYHT
 * @since 2023-05-16
 */
@Service
public class SmsAssetFixedInStorageApplyServiceImpl extends ServiceImpl<SmsAssetFixedInStorageApplyMapper, SmsAssetFixedInStorageApply> implements SmsAssetFixedInStorageApplyService {
    @Autowired
    private SmsAssetFixedInStorageApplyMapper smsAssetFixedInStorageApplyMapper;
    @Autowired
    private SmsAssetFixedInStorageApplyGoodsMapper smsAssetFixedInStorageApplyGoodsMapper;
    @Autowired
    private SmsAssetFixedInStorageApplyGoodsDetailMapper smsAssetFixedInStorageApplyGoodsDetailMapper;
    @Autowired
    private SmsAssetFixedInStorageApplyProcessDetailMapper smsAssetFixedInStorageApplyProcessDetailMapper;
    @Autowired
    private SmsAssetProcessDetailMapper smsAssetProcessDetailMapper;
    @Autowired
    private SmsAssetCategoryManagementMapper smsAssetCategoryManagementMapper;
    @Autowired
    private NewTipsUtil newTipsUtil;
    @Autowired
    private SmsAssetProcessMapper smsAssetProcessMapper;
    @Autowired
    private CacheUtil cacheUtil;
    @Autowired
    private SmsAssetFixedInStorageApplyProcessDetailMPJMapper smsAssetFixedInStorageApplyProcessDetailMPJMapper;
    @Autowired
    private AssetUtil assetUtil;
    @Autowired
    private SmsAssetFixedStorageMapper smsAssetFixedStorageMapper;
    @Resource
    private SmsRoleMapper smsRoleMapper;

    @Override
    @Transactional
    public ResponseResult addFixedInStorageApply(SmsAssetFixedInStorageApplyReq applyReq, String user_id) {
        if (isNullOrEmpty(applyReq.getApplyName()) || isNullOrEmpty(applyReq.getApplyMaintenance())
                || isNullOrEmpty(applyReq.getGoodsList())) {
            return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
        }
        if (applyReq.getGoodsList().size() < 1) {
            return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
        }

        //判断维保时长
        if (applyReq.getApplyMaintenance().equals(0)) {
            return CommonResult.failed(CommonCodeEnum.ASSET_STORAGE_MAINTENANCE_ERR);
        }

        Integer applyCount = smsAssetFixedInStorageApplyMapper.selectCount(new QueryWrapper<SmsAssetFixedInStorageApply>()
                .lambda()
                .eq(SmsAssetFixedInStorageApply::getApplyUserId, user_id)
                .eq(SmsAssetFixedInStorageApply::getAllowStatus, ASSET_ALLOW_STATUS_WAIT_ALLOW));
        if (applyCount >= APPLY_MAX_SIZE) {
            return CommonResult.failed(CommonCodeEnum.ASSET_APPLY_MAX_LIMIT);
        }

        SmsAssetProcess originProcess = smsAssetProcessMapper.selectOne(new QueryWrapper<SmsAssetProcess>()
                .lambda()
                .eq(SmsAssetProcess::getProcessType, ASSET_PROCESS_TYPE_FIXED_IN_STORAGE));
        if (originProcess == null) {
            ExceptionCast.cast(CommonResult.failed(CommonCodeEnum.ASSET_PROCESS_NOT_SETTING));
        }

        List<SmsAssetProcessDetail> fillProcessList =
                smsAssetProcessDetailMapper.selectList(new QueryWrapper<SmsAssetProcessDetail>()
                        .lambda()
                        .eq(SmsAssetProcessDetail::getProcessDetailIsApplicantEdit, true)
                        .eq(SmsAssetProcessDetail::getProcessDetailIsUse, true)
                        .eq(SmsAssetProcessDetail::getProcessId,originProcess.getId())
                        .orderByAsc(SmsAssetProcessDetail::getProcessDetailSort));
        if (fillProcessList != null && fillProcessList.size() > 0) {
            if (applyReq.getProcessList() == null || applyReq.getProcessList().size() < 1) {
                return CommonResult.failed(CommonCodeEnum.ASSET_ALLOW_USER_NOT_SETTING);
            }
            //判断申请人是否将全部需要编辑流程填写
            List<SmsAssetProcessDetail> filterList = fillProcessList
                    .stream()
                    .filter(process -> {
                                List<SmsAssetFixedInStorageApplyProcessDetailReq> result = applyReq.getProcessList()
                                        .stream()
                                        .filter(fillProcess -> fillProcess.getProcessDetailId().equals(process.getId()))
                                        .collect(Collectors.toList());
                                //匹配的去除  未匹配的留下
                                if (result.size() > 0) {
                                    return false;
                                } else {
                                    return true;
                                }
                            }
                    )
                    .collect(Collectors.toList());
            if (filterList.size() > 0) {
                return CommonResult.failed(CommonCodeEnum.ASSET_ALLOW_PROCESS_NOT_FILL);
            }
        }

        Date now_date = new Date();
        String simpleDate = TimeUtil.DateSimpleformat(now_date);
        //获取当天批次
        Integer count = smsAssetFixedInStorageApplyMapper.selectCount(new QueryWrapper<SmsAssetFixedInStorageApply>()
                .lambda()
                .like(SmsAssetFixedInStorageApply::getCreateTime, simpleDate));

        //创建申请表
        SmsAssetFixedInStorageApply smsAssetFixedInStorageApply = new SmsAssetFixedInStorageApply();
        BeanUtils.copyProperties(applyReq, smsAssetFixedInStorageApply);
        smsAssetFixedInStorageApply.setApplyUserId(user_id);
        smsAssetFixedInStorageApply.setAllowStatus(ASSET_ALLOW_STATUS_WAIT_ALLOW);
        smsAssetFixedInStorageApply.setApplySort(count + 1);
        smsAssetFixedInStorageApplyMapper.insert(smsAssetFixedInStorageApply);

        if (smsAssetFixedInStorageApply.getId() == null) {
            ExceptionCast.cast(CommonResult.failed(CommonCodeEnum.FAIL));
        }
        String apply_id = smsAssetFixedInStorageApply.getId();

        //创建入库申请物品记录
        for (SmsAssetFixedInStorageApplyGoodsReq goodsReq : applyReq.getGoodsList()) {
            if (isNullOrEmpty(goodsReq.getAssetBrand()) || isNullOrEmpty(goodsReq.getAssetCategory())
                    || isNullOrEmpty(goodsReq.getAssetModel()) || isNullOrEmpty(goodsReq.getAssetName())
                    || isNullOrEmpty(goodsReq.getAssetNum()) || isNullOrEmpty(goodsReq.getAssetPrice())) {
                ExceptionCast.cast(CommonResult.failed(CommonCodeEnum.INVALID_PARAM));
            }

            if (goodsReq.getAssetResidualRate().compareTo(BigDecimal.ONE) > 0
                    || goodsReq.getAssetResidualRate().compareTo(BigDecimal.ZERO) < 0){
                return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
            }
            //校验残值比单价小
            BigDecimal assetResidualPrice = goodsReq.getAssetPrice().multiply(goodsReq.getAssetResidualRate());
            if (goodsReq.getAssetPrice().compareTo(assetResidualPrice) < 0) {
                return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
            }

            if (isNullOrEmpty(goodsReq.getAssetLifetime(),goodsReq.getAssetResidualRate())){
                ExceptionCast.cast(CommonResult.failed(CommonCodeEnum.INVALID_PARAM));
            }

            SmsAssetCategoryManagement assetCategoryManagement =
                    smsAssetCategoryManagementMapper.selectById(goodsReq.getAssetCategory());
            if (assetCategoryManagement == null || isNullOrEmpty(assetCategoryManagement.getId())) {
                ExceptionCast.cast(CommonResult.failed(CommonCodeEnum.ASSET_CATEGORY_NOT_EXIST));
            }

            //判断是否为根类别
            if (assetCategoryManagement.getId().length() < 3) {
                ExceptionCast.cast(CommonResult.failed(CommonCodeEnum.ASSET_CATEGORY_CAN_NOT_USE_ROOT));
            }

            //判断数量
            if (goodsReq.getAssetNum().equals(0)) {
                ExceptionCast.cast(CommonResult.failed(CommonCodeEnum.ASSET_STORAGE_NUM_ERR));
            }

            SmsAssetFixedInStorageApplyGoods addAssetApplyGoods = new SmsAssetFixedInStorageApplyGoods();
            BeanUtils.copyProperties(goodsReq, addAssetApplyGoods);
            addAssetApplyGoods.setApplyId(apply_id);
            smsAssetFixedInStorageApplyGoodsMapper.insert(addAssetApplyGoods);
        }

        //创建审批流程
        //主流程

        //流程节点
        List<SmsAssetProcessDetail> originProcessDetailList =
                smsAssetProcessDetailMapper.selectList(new QueryWrapper<SmsAssetProcessDetail>()
                        .lambda()
                        .eq(SmsAssetProcessDetail::getProcessDetailIsUse, ASSET_BOOLEAN_TRUE)
                        .eq(SmsAssetProcessDetail::getProcessId, originProcess.getId())
                        .orderByAsc(SmsAssetProcessDetail::getProcessDetailSort));
        if (originProcessDetailList == null || originProcessDetailList.size() < 1) {
            ExceptionCast.cast(CommonResult.failed(CommonCodeEnum.ASSET_PROCESS_NOT_SETTING));
        }
        int sort = 1;
        for (SmsAssetProcessDetail process : originProcessDetailList) {
            //判断管理员是否配置初始流程
            if (process.getProcessDetailIsApplicantEdit().equals(ASSET_BOOLEAN_FALSE)) {
                if (isNullOrEmpty(process.getProcessDetailObjectId()) || isNullOrEmpty(process.getProcessDetailObjectType())) {
                    ExceptionCast.cast(CommonResult.failed(CommonCodeEnum.PAYMENT_PROCESS_NOT_SETTING));
                }
            }

            SmsAssetFixedInStorageApplyProcessDetail addDetail =
                    new SmsAssetFixedInStorageApplyProcessDetail();

            addDetail.setApplyId(apply_id);
            addDetail.setProcessDetailId(process.getId());
            addDetail.setProcessDetailIsSign(process.getProcessDetailIsSign());
            addDetail.setProcessDetailIsStamp(process.getProcessDetailIsStamp());
            addDetail.setProcessDetailName(process.getProcessDetailName());
            addDetail.setProcessDetailStatus(ASSET_ALLOW_STATUS_WAIT_ALLOW);

            addDetail.setProcessDetailSort(sort++);

            //申请人可编辑流程
            if (process.getProcessDetailIsApplicantEdit().equals(ASSET_BOOLEAN_TRUE)) {
                List<SmsAssetFixedInStorageApplyProcessDetailReq> filterList = applyReq.getProcessList()
                        .stream()
                        .filter(fillProcess -> fillProcess.getProcessDetailId().equals(process.getId()))
                        .collect(Collectors.toList());
                if (filterList.size() < 1) {
                    ExceptionCast.cast(CommonResult.failed(CommonCodeEnum.PAYMENT_ALLOW_PROCESS_NOT_FILL));
                }
                SmsAssetFixedInStorageApplyProcessDetailReq fillProcessReq = filterList.get(0);

                if (isNullOrEmpty(fillProcessReq.getProcessDetailObjectId())) {
                    ExceptionCast.cast(CommonResult.failed(CommonCodeEnum.INVALID_PARAM));
                }
                addDetail.setProcessDetailObjectId(fillProcessReq.getProcessDetailObjectId());
                addDetail.setProcessDetailObjectType(ASSET_OBJECT_TYPE_PERSON);
            } else {
                addDetail.setProcessDetailObjectId(process.getProcessDetailObjectId());
                addDetail.setProcessDetailObjectType(process.getProcessDetailObjectType());
            }
            smsAssetFixedInStorageApplyProcessDetailMapper.insert(addDetail);
        }

        //消息通知
        //通知流程第一个节点
        SmsAssetFixedInStorageApplyProcessDetail firstDetail =
                smsAssetFixedInStorageApplyProcessDetailMapper.selectOne(new QueryWrapper<SmsAssetFixedInStorageApplyProcessDetail>()
                        .lambda()
                        .eq(SmsAssetFixedInStorageApplyProcessDetail::getApplyId, apply_id)
                        .eq(SmsAssetFixedInStorageApplyProcessDetail::getProcessDetailSort, 1)
                        .orderByAsc(SmsAssetFixedInStorageApplyProcessDetail::getProcessDetailSort));
        RangeTypeEnum rangeTypeEnum;
        if (firstDetail.getProcessDetailIsApplicantEdit() == ASSET_BOOLEAN_TRUE) {
            rangeTypeEnum = RangeTypeEnum.RANGE_TYPE_ENUM_PERSON;
        } else {
            if (firstDetail.getProcessDetailObjectType() == ASSET_OBJECT_TYPE_PERSON) {
                rangeTypeEnum = RangeTypeEnum.RANGE_TYPE_ENUM_PERSON;
            } else {
                rangeTypeEnum = RangeTypeEnum.RANGE_TYPE_ENUM_ROLE;
            }
        }

        List<String> rangeList = new ArrayList<>();
        rangeList.add(firstDetail.getProcessDetailObjectId());

        newTipsUtil.addNewTips(TipsTypeEnum.TIPS_TYPE_ENUM_ALLOW,
                user_id,
                rangeTypeEnum,
                rangeList,
                AppTypeEnum.APP_TYPE_ENUM_ASSET_WAREHOUSING,
                apply_id,
                firstDetail.getId());
        return CommonResult.success();
    }

    @Override
    @Transactional
    public ResponseResult cancelFixedInStorageApply(SmsAssetFixedInStorageApplyReq applyReq, String user_id) {
        if (isNullOrEmpty(applyReq.getApplyId())) {
            return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
        }

        SmsAssetFixedInStorageApply assetApply = smsAssetFixedInStorageApplyMapper.selectOne(new QueryWrapper<SmsAssetFixedInStorageApply>()
                .lambda()
                .eq(SmsAssetFixedInStorageApply::getApplyUserId, user_id)
                .eq(SmsAssetFixedInStorageApply::getId, applyReq.getApplyId()));
        if (assetApply == null) {
            return CommonResult.failed(CommonCodeEnum.ASSET_APPLY_NOT_EXIST);
        }

        if (assetApply.getAllowStatus() != EXAMINE_STATUS_WAIT_ALLOW) {
            return CommonResult.failed(CommonCodeEnum.PAYMENT_CANCEL_FAIL_ALLOWED);
        }

        //判断是否审批中
        List<SmsAssetFixedInStorageApplyProcessDetail> detailList =
                smsAssetFixedInStorageApplyProcessDetailMapper.selectList(new QueryWrapper<SmsAssetFixedInStorageApplyProcessDetail>()
                        .lambda()
                        .eq(SmsAssetFixedInStorageApplyProcessDetail::getApplyId, applyReq.getApplyId())
                        .eq(SmsAssetFixedInStorageApplyProcessDetail::getProcessDetailStatus, EXAMINE_STATUS_PASS));
        if (detailList != null && detailList.size() > 0) {
            return CommonResult.failed(CommonCodeEnum.ASSET_CANCEL_FAIL_ALLOWING);
        }

        //撤回审批
        SmsAssetFixedInStorageApply cancelApply = new SmsAssetFixedInStorageApply();
        cancelApply.setId(applyReq.getApplyId());
        cancelApply.setAllowStatus(ASSET_ALLOW_STATUS_CANCEL);
        cancelApply.setEndTime(new Date());
        smsAssetFixedInStorageApplyMapper.updateById(cancelApply);

        //修改节点状态
        SmsAssetFixedInStorageApplyProcessDetail cancelProcessDetail = new SmsAssetFixedInStorageApplyProcessDetail();
        cancelProcessDetail.setProcessDetailStatus(ASSET_ALLOW_STATUS_CANCEL);

        smsAssetFixedInStorageApplyProcessDetailMapper.update(cancelProcessDetail, new QueryWrapper<SmsAssetFixedInStorageApplyProcessDetail>()
                .lambda()
                .eq(SmsAssetFixedInStorageApplyProcessDetail::getApplyId, applyReq.getApplyId()));

        //消息通知
        newTipsUtil.cancelFinishTips(applyReq.getApplyId());
        return CommonResult.success();
    }

    @Override
    public ResponseResult getAssetFixedInStorageApplyList(String user_id, Integer apply_type, Integer pageNum, Integer pageSize) {
        if (isNullOrEmpty(apply_type)) {
            return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
        }
        List<SmsAssetFixedInStorageApplyResp> respList = new ArrayList<>();
        int total = 0;
        if (apply_type == ASSET_ALLOW_TYPE_APPLY) {
            Page<SmsAssetFixedInStorageApply> page = new Page<>(pageNum, pageSize);
            QueryWrapper<SmsAssetFixedInStorageApply> queryWrapper = new QueryWrapper<>();
            queryWrapper.lambda()
                    .eq(SmsAssetFixedInStorageApply::getApplyUserId, user_id)
                    .orderByDesc(SmsAssetFixedInStorageApply::getCreateTime);
            smsAssetFixedInStorageApplyMapper.selectPage(page, queryWrapper);
            respList = page.getRecords()
                    .stream()
                    .map(apply -> {
                        SmsAssetFixedInStorageApplyResp storageApplyResp =
                                new SmsAssetFixedInStorageApplyResp();
                        BeanUtils.copyProperties(apply, storageApplyResp);
                        storageApplyResp.setApplyId(apply.getId());

                        SmsUser smsUser = cacheUtil.getUserInfo(apply.getApplyUserId());
                        SmsSearchUserResp userResp = new SmsSearchUserResp();
                        if (smsUser != null) {
                            BeanUtils.copyProperties(smsUser, userResp);
                        }
                        storageApplyResp.setApplyUserInfo(userResp);

                        return storageApplyResp;
                    })
                    .collect(Collectors.toList());
            total = (int) page.getTotal();
        } else if (apply_type == ASSET_ALLOW_TYPE_ALLOWED) {
            Page<SmsAssetFixedInStorageApplyMPJResp> page = new Page<>(pageNum, pageSize);
            MPJLambdaWrapper<SmsAssetFixedInStorageApplyProcessDetail> mpjLambdaWrapper = new MPJLambdaWrapper<>();
            mpjLambdaWrapper.selectAll(SmsAssetFixedInStorageApplyProcessDetail.class)
                    .selectAll(SmsAssetFixedInStorageApply.class)
                    .selectAs(SmsAssetFixedInStorageApply::getCreateTime, "applyCreateTime")
                    .selectAs(SmsAssetFixedInStorageApplyProcessDetail::getId, "detailId")
                    .leftJoin(SmsAssetFixedInStorageApply.class, SmsAssetFixedInStorageApply::getId, SmsAssetFixedInStorageApplyProcessDetail::getApplyId)
                    .eq(SmsAssetFixedInStorageApplyProcessDetail::getAllowUserId, user_id)
                    .orderByDesc(SmsAssetFixedInStorageApply::getCreateTime)
                    .orderByDesc(SmsAssetFixedInStorageApplyProcessDetail::getEndTime)
            ;

            smsAssetFixedInStorageApplyProcessDetailMPJMapper.selectJoinPage(page, SmsAssetFixedInStorageApplyMPJResp.class, mpjLambdaWrapper);

            respList = page.getRecords()
                    .stream()
                    .map(smsMPJResp -> {
                        SmsAssetFixedInStorageApplyResp applyResp = new SmsAssetFixedInStorageApplyResp();
                        BeanUtils.copyProperties(smsMPJResp, applyResp);
                        applyResp.setCreateTime(smsMPJResp.getApplyCreateTime());
                        applyResp.setEndTime(smsMPJResp.getApplyEndTime());

                        SmsUser applyUser = cacheUtil.getUserInfo(applyResp.getApplyUserId());
                        SmsSearchUserResp applyUserResp = new SmsSearchUserResp();
                        if (applyUser != null) {
                            BeanUtils.copyProperties(applyUser, applyUserResp);
                        }
                        applyResp.setApplyUserInfo(applyUserResp);

                        SmsUser allowUser = cacheUtil.getUserInfo(applyResp.getAllowUserId());
                        SmsSearchUserResp allowUserResp = new SmsSearchUserResp();
                        if (allowUser != null) {
                            BeanUtils.copyProperties(allowUser, allowUserResp);
                        }
                        applyResp.setAllowUserInfo(allowUserResp);

                        return applyResp;
                    })
                    .collect(Collectors.toList());
            total = (int) page.getTotal();
        } else if (apply_type == ASSET_ALLOW_TYPE_WAIT_ALLOW) {
            List<String> roleList = cacheUtil.getRoleList(user_id);

            //获取所有待审批申请流程节点
            List<SmsAssetFixedInStorageApplyProcessDetail> allDetailList =
                    smsAssetFixedInStorageApplyProcessDetailMapper.selectList(new QueryWrapper<SmsAssetFixedInStorageApplyProcessDetail>()
                            .lambda()
                            .eq(SmsAssetFixedInStorageApplyProcessDetail::getProcessDetailStatus, ASSET_ALLOW_STATUS_WAIT_ALLOW));

            List<SmsAssetFixedInStorageApplyProcessDetail> filterDetailList = allDetailList.stream()
                    .filter(detail -> {
                        if (detail.getProcessDetailIsApplicantEdit() == ASSET_BOOLEAN_TRUE) {
                            if (!detail.getProcessDetailObjectId().equals(user_id)) {
                                return false;
                            }
                        } else {
                            if (detail.getProcessDetailObjectType() == ASSET_OBJECT_TYPE_PERSON) {
                                if (!detail.getProcessDetailObjectId().equals(user_id)) {
                                    return false;
                                }
                            } else {
                                List<String> filterRoleList = roleList.stream().filter(role -> role.equals(detail.getProcessDetailObjectId())).collect(Collectors.toList());
                                if (filterRoleList.size() < 1) {
                                    return false;
                                }
                            }
                        }

                        if (detail.getProcessDetailSort().equals(1)) {
                            return true;
                        }
                        //判断上一个流程节点是否完成
                        SmsAssetFixedInStorageApplyProcessDetail preDetail =
                                smsAssetFixedInStorageApplyProcessDetailMapper.selectOne(new QueryWrapper<SmsAssetFixedInStorageApplyProcessDetail>()
                                        .lambda()
                                        .eq(SmsAssetFixedInStorageApplyProcessDetail::getApplyId, detail.getApplyId())
                                        .eq(SmsAssetFixedInStorageApplyProcessDetail::getProcessDetailSort, detail.getProcessDetailSort() - 1)
                                        .eq(SmsAssetFixedInStorageApplyProcessDetail::getProcessDetailStatus, ASSET_ALLOW_STATUS_PASS));
                        if (preDetail == null || isNullOrEmpty(preDetail.getId())) {
                            return false;
                        }
                        return true;
                    })
                    .collect(Collectors.toList());
            if (filterDetailList.size() > 0) {
                List<String> detailIDList = filterDetailList.stream().map(SmsAssetFixedInStorageApplyProcessDetail::getId).collect(Collectors.toList());

                Page<SmsAssetFixedInStorageApplyMPJResp> page = new Page<>(pageNum, pageSize);
                MPJLambdaWrapper<SmsAssetFixedInStorageApplyProcessDetail> mpjLambdaWrapper = new MPJLambdaWrapper<>();
                mpjLambdaWrapper.selectAll(SmsAssetFixedInStorageApplyProcessDetail.class)
                        .selectAll(SmsAssetFixedInStorageApply.class)
                        .selectAs(SmsAssetFixedInStorageApply::getCreateTime, "applyCreateTime")
                        .selectAs(SmsAssetFixedInStorageApplyProcessDetail::getId, "detailId")
                        .leftJoin(SmsAssetFixedInStorageApply.class, SmsAssetFixedInStorageApply::getId, SmsAssetFixedInStorageApplyProcessDetail::getApplyId)
                        .in(SmsAssetFixedInStorageApplyProcessDetail::getId, detailIDList)
                        .orderByDesc(SmsAssetFixedInStorageApply::getCreateTime)
                        .orderByDesc(SmsAssetFixedInStorageApplyProcessDetail::getCreateTime)
                ;
                smsAssetFixedInStorageApplyProcessDetailMPJMapper.selectJoinPage(page, SmsAssetFixedInStorageApplyMPJResp.class, mpjLambdaWrapper);

                respList = page.getRecords()
                        .stream()
                        .map(smsApplyMPJResp -> {
                            SmsAssetFixedInStorageApplyResp applyResp = new SmsAssetFixedInStorageApplyResp();
                            BeanUtils.copyProperties(smsApplyMPJResp, applyResp);
                            applyResp.setCreateTime(smsApplyMPJResp.getApplyCreateTime());

                            SmsUser applyUser = cacheUtil.getUserInfo(smsApplyMPJResp.getApplyUserId());
                            SmsSearchUserResp smsExamineUserResp = new SmsSearchUserResp();
                            if (applyUser != null) {
                                BeanUtils.copyProperties(applyUser, smsExamineUserResp);
                            }
                            applyResp.setApplyUserInfo(smsExamineUserResp);

                            return applyResp;
                        })
                        .collect(Collectors.toList());
                total = (int) page.getTotal();
            }
        }
        return CommonResult.success(respList, total);
    }

    @Override
    public ResponseResult getAssetFixedInStorageApplyDetail(String apply_id, String user_id) {
        if (isNullOrEmpty(apply_id)) {
            return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
        }
        SmsAssetFixedInStorageApply assetApply = smsAssetFixedInStorageApplyMapper.selectById(apply_id);
        if (assetApply == null || isNullOrEmpty(assetApply.getId())) {
            return CommonResult.failed(CommonCodeEnum.ASSET_APPLY_NOT_EXIST);
        }

        SmsAssetFixedInStorageApplyResp applyResp = new SmsAssetFixedInStorageApplyResp();
        BeanUtils.copyProperties(assetApply, applyResp);
        applyResp.setApplyId(assetApply.getId());

        SmsUser smsUser = cacheUtil.getUserInfo(applyResp.getApplyUserId());
        SmsSearchUserResp smsUserResp = new SmsSearchUserResp();
        if (smsUser != null) {
            BeanUtils.copyProperties(smsUser, smsUserResp);
        }
        applyResp.setApplyUserInfo(smsUserResp);

        //封装流程节点
        List<SmsAssetFixedInStorageApplyProcessDetailResp> detailRespList =
                smsAssetFixedInStorageApplyProcessDetailMapper.selectList(new QueryWrapper<SmsAssetFixedInStorageApplyProcessDetail>()
                        .lambda()
                        .eq(SmsAssetFixedInStorageApplyProcessDetail::getApplyId, apply_id)
                        .orderByAsc(SmsAssetFixedInStorageApplyProcessDetail::getProcessDetailSort))
                        .stream()
                        .map(detail -> {
                            SmsAssetFixedInStorageApplyProcessDetailResp detailResp = new SmsAssetFixedInStorageApplyProcessDetailResp();
                            BeanUtils.copyProperties(detail, detailResp);

                            if (!isNullOrEmpty(detailResp.getAllowUserId())) {
                                SmsUser userInfo = cacheUtil.getUserInfo(detailResp.getAllowUserId());
                                SmsSearchUserResp smsSearchUserResp = new SmsSearchUserResp();
                                if (userInfo != null) {
                                    BeanUtils.copyProperties(userInfo, smsSearchUserResp);
                                }
                                detailResp.setAllowUserInfo(smsSearchUserResp);
                            }

                            if(detail.getProcessDetailObjectType() == PROCESS_OBJECT_TYPE_PERSON){
                                SmsUser allowUser = cacheUtil.getUserInfo(detail.getProcessDetailObjectId());
                                if(allowUser != null) {
                                    detailResp.setObjectName(allowUser.getRealName());
                                    detailResp.setObjectPic(allowUser.getUserPic());
                                }
                            }else {
                                SmsRole smsRole = smsRoleMapper.selectById(detail.getProcessDetailObjectId());
                                if(smsRole != null) {
                                    detailResp.setObjectName(smsRole.getRoleName());
                                }
                            }
                            return detailResp;
                        })
                        .collect(Collectors.toList());
        applyResp.setProcessList(detailRespList);

        //封装物品信息
        List<SmsAssetFixedInStorageApplyGoodsResp> goodsList =
                smsAssetFixedInStorageApplyGoodsMapper.selectList(new QueryWrapper<SmsAssetFixedInStorageApplyGoods>()
                        .lambda()
                        .eq(SmsAssetFixedInStorageApplyGoods::getApplyId, apply_id))
                        .stream()
                        .map(goods -> {
                            SmsAssetFixedInStorageApplyGoodsResp goodsResp = new SmsAssetFixedInStorageApplyGoodsResp();
                            BeanUtils.copyProperties(goods, goodsResp);

                            List<String> assetPreIdList = smsAssetFixedInStorageApplyGoodsDetailMapper.selectList(new QueryWrapper<SmsAssetFixedInStorageApplyGoodsDetail>()
                                    .lambda()
                                    .eq(SmsAssetFixedInStorageApplyGoodsDetail::getAssetGoodsId, goods.getId()))
                                    .stream()
                                    .map(SmsAssetFixedInStorageApplyGoodsDetail::getAssetPreId)
                                    .collect(Collectors.toList());

                            SmsAssetCategoryManagement categoryManagement = smsAssetCategoryManagementMapper.selectById(goods.getAssetCategory());
                            if (categoryManagement != null) {
                                goodsResp.setAssetCategoryName(categoryManagement.getCategoryName());
                            }

                            goodsResp.setAssetPreIdList(assetPreIdList);
                            return goodsResp;
                        })
                        .collect(Collectors.toList());
        applyResp.setGoodsList(goodsList);
        return CommonResult.success(applyResp);
    }

    @Override
    @Transactional
    public ResponseResult allowAssetFixedInStorageApply(SmsAssetFixedInStorageApplyAllowReq smsAssetFixedInStorageApplyAllowReq, String user_id) {
        if (isNullOrEmpty(smsAssetFixedInStorageApplyAllowReq.getApplyId()) || isNullOrEmpty(smsAssetFixedInStorageApplyAllowReq.getDetailId())
                || isNullOrEmpty(smsAssetFixedInStorageApplyAllowReq.getProcessDetailStatus())) {
            return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
        }

        if (smsAssetFixedInStorageApplyAllowReq.getProcessDetailStatus() != ASSET_ALLOW_STATUS_PASS
                && smsAssetFixedInStorageApplyAllowReq.getProcessDetailStatus() != ASSET_ALLOW_STATUS_DENY) {
            return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
        }

        SmsAssetFixedInStorageApply inStorageApply = smsAssetFixedInStorageApplyMapper.selectById(smsAssetFixedInStorageApplyAllowReq.getApplyId());
        if (inStorageApply == null || isNullOrEmpty(inStorageApply.getId())) {
            return CommonResult.failed(CommonCodeEnum.ASSET_APPLY_NOT_EXIST);
        }

        SmsAssetFixedInStorageApplyProcessDetail processDetail =
                smsAssetFixedInStorageApplyProcessDetailMapper.selectOne(new QueryWrapper<SmsAssetFixedInStorageApplyProcessDetail>()
                        .lambda()
                        .eq(SmsAssetFixedInStorageApplyProcessDetail::getApplyId, smsAssetFixedInStorageApplyAllowReq.getApplyId())
                        .eq(SmsAssetFixedInStorageApplyProcessDetail::getId, smsAssetFixedInStorageApplyAllowReq.getDetailId())
                        .eq(SmsAssetFixedInStorageApplyProcessDetail::getProcessDetailStatus, ASSET_ALLOW_STATUS_WAIT_ALLOW));
        if (processDetail == null || isNullOrEmpty(processDetail.getId())) {
            return CommonResult.failed(CommonCodeEnum.ASSET_ALLOW_FAIL);
        }

        //判断该节点是否本人审批（防止跳节点审批）
        if (processDetail.getProcessDetailObjectType() == ASSET_OBJECT_TYPE_PERSON) {
            if (!processDetail.getProcessDetailObjectId().equals(user_id)) {
                return CommonResult.failed(CommonCodeEnum.ASSET_ALLOW_FAIL);
            }
        } else {
            List<String> roleList = cacheUtil.getRoleList(user_id);
            List<String> filterRoleList = roleList.stream().filter(role -> role.equals(processDetail.getProcessDetailObjectId())).collect(Collectors.toList());
            if (filterRoleList.size() < 1) {
                return CommonResult.failed(CommonCodeEnum.ASSET_ALLOW_FAIL);
            }
        }

        if (!processDetail.getProcessDetailSort().equals(1)) {
            SmsAssetFixedInStorageApplyProcessDetail preDetail =
                    smsAssetFixedInStorageApplyProcessDetailMapper.selectOne(new QueryWrapper<SmsAssetFixedInStorageApplyProcessDetail>()
                            .lambda()
                            .eq(SmsAssetFixedInStorageApplyProcessDetail::getApplyId, smsAssetFixedInStorageApplyAllowReq.getApplyId())
                            .eq(SmsAssetFixedInStorageApplyProcessDetail::getProcessDetailSort, processDetail.getProcessDetailSort() - 1));
            if (preDetail != null && isNullOrEmpty(preDetail.getId())) {
                if (preDetail.getProcessDetailStatus() != ASSET_ALLOW_STATUS_PASS) {
                    return CommonResult.failed(CommonCodeEnum.ASSET_ALLOW_FAIL);
                }
            }
        }

        SmsAssetFixedInStorageApplyProcessDetail allowDetail = new SmsAssetFixedInStorageApplyProcessDetail();
        allowDetail.setId(smsAssetFixedInStorageApplyAllowReq.getDetailId());
        allowDetail.setProcessDetailStatus(smsAssetFixedInStorageApplyAllowReq.getProcessDetailStatus());
        if (!isNullOrEmpty(smsAssetFixedInStorageApplyAllowReq.getProcessDetailRemark())) {
            allowDetail.setProcessDetailRemark(smsAssetFixedInStorageApplyAllowReq.getProcessDetailRemark());
        }
        Date nowDate = new Date();
        allowDetail.setEndTime(nowDate);
        allowDetail.setAllowUserId(user_id);

        if (processDetail.getProcessDetailIsSign() == ASSET_BOOLEAN_TRUE) {
            if (isNullOrEmpty(smsAssetFixedInStorageApplyAllowReq.getProcessDetailSign())) {
                return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
            }
            allowDetail.setProcessDetailSign(smsAssetFixedInStorageApplyAllowReq.getProcessDetailSign());
        }
        if (processDetail.getProcessDetailIsStamp() == ASSET_BOOLEAN_TRUE) {
            if (isNullOrEmpty(smsAssetFixedInStorageApplyAllowReq.getProcessDetailStamp())) {
                return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
            }
            allowDetail.setProcessDetailStamp(smsAssetFixedInStorageApplyAllowReq.getProcessDetailStamp());
        }
        smsAssetFixedInStorageApplyProcessDetailMapper.updateById(allowDetail);

        boolean is_done = false;

        //判断是否最后一个节点 是否驳回
        Integer detailCount = smsAssetFixedInStorageApplyProcessDetailMapper.selectCount(new QueryWrapper<SmsAssetFixedInStorageApplyProcessDetail>()
                .lambda()
                .eq(SmsAssetFixedInStorageApplyProcessDetail::getApplyId, smsAssetFixedInStorageApplyAllowReq.getApplyId()));
        if (detailCount.equals(processDetail.getProcessDetailSort()) || smsAssetFixedInStorageApplyAllowReq.getProcessDetailStatus() == ASSET_ALLOW_STATUS_DENY) {
            is_done = true;

            SmsAssetFixedInStorageApply updateApply = new SmsAssetFixedInStorageApply();
            updateApply.setId(smsAssetFixedInStorageApplyAllowReq.getApplyId());
            updateApply.setEndTime(nowDate);
            updateApply.setAllowStatus(smsAssetFixedInStorageApplyAllowReq.getProcessDetailStatus());
            smsAssetFixedInStorageApplyMapper.updateById(updateApply);
        }

        //流程结束且同意，预生成资产加入资产库
        Date now_date = new Date();
        if (detailCount.equals(processDetail.getProcessDetailSort()) && smsAssetFixedInStorageApplyAllowReq.getProcessDetailStatus() == ASSET_ALLOW_STATUS_PASS) {
            List<SmsAssetFixedInStorageApplyGoods> goodsList =
                    smsAssetFixedInStorageApplyGoodsMapper.selectList(new QueryWrapper<SmsAssetFixedInStorageApplyGoods>()
                            .lambda()
                            .eq(SmsAssetFixedInStorageApplyGoods::getApplyId, smsAssetFixedInStorageApplyAllowReq.getApplyId()));
            if (goodsList != null && goodsList.size() > 0) {
                int goods_count = 1;
                for (SmsAssetFixedInStorageApplyGoods goods : goodsList) {
                    //根据物品数量生成等量资产id
                    String category_id = goods.getAssetCategory();
                    for (int i = 0; i < goods.getAssetNum(); i++) {
                        try {
                            String asset_id = assetUtil.createAssetStorageID(category_id,
                                    now_date,
                                    IN_STORAGE_METHOD_FIXED_APPLY,
                                    inStorageApply.getApplySort(),
                                    goods_count++,
                                    i+1);

                            SmsAssetFixedInStorageApplyGoodsDetail addGoodsDetail = new SmsAssetFixedInStorageApplyGoodsDetail();
                            addGoodsDetail.setAssetGoodsId(goods.getId());
                            addGoodsDetail.setAssetPreId(asset_id);
                            addGoodsDetail.setApplyId(inStorageApply.getId());
                            smsAssetFixedInStorageApplyGoodsDetailMapper.insert(addGoodsDetail);

                            SmsAssetFixedStorage addAsset = new SmsAssetFixedStorage();
                            addAsset.setId(asset_id);
                            addAsset.setAssetCategory(goods.getAssetCategory());
                            addAsset.setAssetNum(1);
                            addAsset.setAddUserId(inStorageApply.getApplyUserId());
                            addAsset.setAssetStatus(ASSET_STATUS_IN_STORAGE);
                            addAsset.setAssetBrand(goods.getAssetBrand());
                            addAsset.setAssetMaintenanceDuration(inStorageApply.getApplyMaintenance());
                            addAsset.setAssetModel(goods.getAssetModel());
                            addAsset.setAssetUnit(goods.getAssetUnit());
                            addAsset.setAssetPlace(goods.getAssetPlace());
                            addAsset.setAssetName(goods.getAssetName());
                            addAsset.setAssetPrice(goods.getAssetPrice());
                            addAsset.setAssetMaintenanceExpire(TimeUtil.AddMonths(nowDate, inStorageApply.getApplyMaintenance()));


                            //校验残值比单价小
                            BigDecimal assetResidualPrice = goods.getAssetPrice().multiply(goods.getAssetResidualRate());
                            //资产折旧
                            addAsset.setAssetLifetime(goods.getAssetLifetime());
                            addAsset.setAssetResidualPrice(assetResidualPrice);
                            addAsset.setAssetRealPrice(goods.getAssetPrice());
                            addAsset.setAssetTotalDepreciationPrice(new BigDecimal(0));
                            addAsset.setAssetBuyMonth(0);
                            addAsset.setAssetResidualRate(goods.getAssetResidualRate());
                            //计算每月折旧和误差
                            roundToTwoDecimals(addAsset);

                            smsAssetFixedStorageMapper.insert(addAsset);
                        } catch (Exception e) {
                            e.printStackTrace();
                            ExceptionCast.cast(CommonResult.failed(CommonCodeEnum.FAIL));
                        }
                    }
//                    List<String> assetIDList = smsAssetFixedInStorageApplyGoodsDetailMapper.selectList(new QueryWrapper<SmsAssetFixedInStorageApplyGoodsDetail>()
//                            .lambda()
//                            .eq(SmsAssetFixedInStorageApplyGoodsDetail::getAssetGoodsId, goods.getId()))
//                            .stream()
//                            .map(SmsAssetFixedInStorageApplyGoodsDetail::getAssetPreId)
//                            .collect(Collectors.toList());
//                    if (assetIDList.size() > 0) {
//                        for (String asset_id : assetIDList) {
//                            SmsAssetFixedStorage addAsset = new SmsAssetFixedStorage();
//                            addAsset.setId(asset_id);
//                            addAsset.setAssetCategory(goods.getAssetCategory());
//                            addAsset.setAssetNum(1);
//                            addAsset.setAddUserId(inStorageApply.getApplyUserId());
//                            addAsset.setAssetStatus(ASSET_STATUS_IN_STORAGE);
//                            addAsset.setAssetBrand(goods.getAssetBrand());
//                            addAsset.setAssetMaintenanceDuration(inStorageApply.getApplyMaintenance());
//                            addAsset.setAssetModel(goods.getAssetModel());
//                            addAsset.setAssetName(goods.getAssetName());
//                            addAsset.setAssetPrice(goods.getAssetPrice());
//                            addAsset.setAssetMaintenanceExpire(TimeUtil.AddMonths(nowDate, inStorageApply.getApplyMaintenance()));
//                            smsAssetFixedStorageMapper.insert(addAsset);
//                        }
//                    }
                }
            }
        }

        //节点驳回 重置其余节点状态
        if (smsAssetFixedInStorageApplyAllowReq.getProcessDetailStatus() == ASSET_ALLOW_STATUS_DENY) {
            SmsAssetFixedInStorageApplyProcessDetail updateDenyDetail =
                    new SmsAssetFixedInStorageApplyProcessDetail();
            updateDenyDetail.setProcessDetailStatus(ASSET_ALLOW_STATUS_DENY_FINISH);
            smsAssetFixedInStorageApplyProcessDetailMapper.update(updateDenyDetail, new QueryWrapper<SmsAssetFixedInStorageApplyProcessDetail>()
                    .lambda()
                    .eq(SmsAssetFixedInStorageApplyProcessDetail::getApplyId, smsAssetFixedInStorageApplyAllowReq.getApplyId())
                    .eq(SmsAssetFixedInStorageApplyProcessDetail::getProcessDetailStatus, ASSET_ALLOW_STATUS_WAIT_ALLOW));
        }

        //消息通知
        if (is_done) {
            boolean result_status = false;
            if (smsAssetFixedInStorageApplyAllowReq.getProcessDetailStatus() == ASSET_ALLOW_STATUS_PASS) {
                result_status = true;
            }
            newTipsUtil.allowFinishTips(smsAssetFixedInStorageApplyAllowReq.getApplyId(), user_id, result_status);
        } else {
            SmsAssetFixedInStorageApplyProcessDetail nextDetail =
                    smsAssetFixedInStorageApplyProcessDetailMapper.selectOne(new QueryWrapper<SmsAssetFixedInStorageApplyProcessDetail>()
                            .lambda()
                            .eq(SmsAssetFixedInStorageApplyProcessDetail::getApplyId, smsAssetFixedInStorageApplyAllowReq.getApplyId())
                            .eq(SmsAssetFixedInStorageApplyProcessDetail::getProcessDetailSort, processDetail.getProcessDetailSort() + 1));
            RangeTypeEnum rangeTypeEnum;
            if (nextDetail.getProcessDetailIsApplicantEdit() == ASSET_BOOLEAN_TRUE) {
                rangeTypeEnum = RangeTypeEnum.RANGE_TYPE_ENUM_PERSON;
            } else {
                if (nextDetail.getProcessDetailObjectType() == ASSET_OBJECT_TYPE_PERSON) {
                    rangeTypeEnum = RangeTypeEnum.RANGE_TYPE_ENUM_PERSON;
                } else {
                    rangeTypeEnum = RangeTypeEnum.RANGE_TYPE_ENUM_ROLE;
                }
            }

            List<String> rangeIDList = new ArrayList<>();
            rangeIDList.add(nextDetail.getProcessDetailObjectId());
            newTipsUtil.allowContinueTips(smsAssetFixedInStorageApplyAllowReq.getApplyId(),
                    user_id,
                    rangeTypeEnum,
                    rangeIDList,
                    nextDetail.getId());
        }
        return CommonResult.success();
    }

    private void roundToTwoDecimals(SmsAssetFixedStorage addAssetStorage) {
        BigDecimal lifetimeResult = new BigDecimal(addAssetStorage.getAssetLifetime());
        //初始价格
        //总价-残值 = 总折旧价值（subResult）
        //月折旧（result） = 总折旧价值/资产寿命
        //根据误差计算出最后一个月折旧（lastMonth）
        //用月折旧数倒推月折旧率
        BigDecimal dividend = addAssetStorage.getAssetPrice();
        BigDecimal subResult = addAssetStorage.getAssetPrice().subtract(addAssetStorage.getAssetResidualPrice());
        BigDecimal result = divideAndRound(subResult,
                lifetimeResult,
                2);

        // 根据结果与除数计算回被除数
        BigDecimal approxDividend = result.multiply(lifetimeResult);

        // 计算误差
        BigDecimal error = dividend.subtract(approxDividend);
        BigDecimal lastMonth = result.subtract(error);

        addAssetStorage.setAssetPerDepreciationPrice(result);
        addAssetStorage.setAssetLastMonthDepreciationPrice(lastMonth);
        addAssetStorage.setAssetDepreciationRate(divideAndRound(result,addAssetStorage.getAssetPrice(),2));
        addAssetStorage.setAssetLastMonthDepreciationRate(divideAndRound(lastMonth,addAssetStorage.getAssetPrice(),2));
    }

    private BigDecimal divideAndRound(BigDecimal dividend, BigDecimal divisor, int scale) {
        return dividend.divide(divisor, scale, RoundingMode.HALF_UP);
    }

    @Override
    public ResponseResult getAssetFixedInStorageApplyAllList(Integer allowStatus, String applyName, Integer pageNum, Integer pageSize) {
        Page<SmsAssetFixedInStorageApply> page = new Page<>(pageNum,pageSize);
        LambdaQueryWrapper<SmsAssetFixedInStorageApply> fixedInStorageApplyLambdaQueryWrapper = new LambdaQueryWrapper<SmsAssetFixedInStorageApply>()
                .orderByDesc(SmsAssetFixedInStorageApply::getCreateTime);
        if (!isNullOrEmpty(applyName)) {
            fixedInStorageApplyLambdaQueryWrapper.like(SmsAssetFixedInStorageApply::getApplyName,applyName);
        }
        if (!isNullOrEmpty(allowStatus)) {
            fixedInStorageApplyLambdaQueryWrapper.eq(SmsAssetFixedInStorageApply::getAllowStatus,allowStatus);
        }
        smsAssetFixedInStorageApplyMapper.selectPage(page,fixedInStorageApplyLambdaQueryWrapper);
        List<SmsAssetFixedInStorageApplyResp> respList = page.getRecords()
                .stream()
                .map(smsAssetFixedInStorageApply -> {
                    SmsAssetFixedInStorageApplyResp applyResp = new SmsAssetFixedInStorageApplyResp();
                    BeanUtils.copyProperties(smsAssetFixedInStorageApply, applyResp);
                    applyResp.setApplyId(smsAssetFixedInStorageApply.getId());

                    SmsUser smsUser = cacheUtil.getUserInfo(applyResp.getApplyUserId());
                    SmsSearchUserResp smsUserResp = new SmsSearchUserResp();
                    if (smsUser != null) {
                        BeanUtils.copyProperties(smsUser, smsUserResp);
                    }
                    applyResp.setApplyUserInfo(smsUserResp);

                    return applyResp;
                })
                .collect(Collectors.toList());
        return CommonResult.success(respList,(int)page.getTotal());
    }



}
